package aaa.screen;

import greendroid.app.GDListActivity;
import greendroid.widget.ActionBarItem;
import greendroid.widget.ActionBarItem.Type;
import greendroid.widget.ItemAdapter;
import greendroid.widget.item.DescriptionItem;
import greendroid.widget.item.Item;
import greendroid.widget.item.SeparatorItem;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import aaa.database.Database;
import aaa.schedule.Lesson;
import aaa.schedule.ScheduleConstants;
import aaa.schedule.UpdateListener;
import aaa.update.UpdateNotifier;
import aaa.util.StringUtils;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.os.Bundle;

/**
 * View displaying the information about a lesson.
 * 
 * @author		Schnell Michaël, Zanette Sébastien
 */
public class LessonScreen extends GDListActivity implements UpdateListener, ScheduleConstants {

	/**
	 * List of the graphical components used to display this lesson.
	 */
	protected List<Item> items ;

	/**
	 * Container for the information about this lesson.
	 */
	protected Lesson lesson ;

	/**
	 * Dialog displayed when the containing schedule is being updated.
	 */
	protected ProgressDialog updateDialog ;

	/**
	 * Id of the edit item in the action bar.
	 */
	protected static final int ITEM_EDIT = 1 ;


	/**
	 * Initializes this view.
	 */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState) ;
		this.lesson = this.getIntentLesson() ;

		this.setTitle(this.lesson.getTitle()) ;
		this.initActionBar() ;
	}// onCreate(Bundle)

	/**
	 * Adds this view to the listener list of the {@code UpdateManager}.
	 */
	@Override
	protected void onStart() {
		super.onStart() ;
//		UpdateManager um = UpdateManager.getInstance() ;
//		um.addListener(this) ;
//		int status = um.getScheduleStatus(this.lesson.getSchedule()) ;
		UpdateNotifier.addListener(this) ;
		Database db = new Database(this) ;
		int status = db.getScheduleStatus(this.lesson.getSchedule()) ;
		if (status != STATUS_UPDATING) {
			this.init() ;
		} else {
			this.onUpdate(this.lesson.getSchedule(), status) ;
		}// if
	}// onStart()

	/**
	 * Removes this view from the listener list of the {@code UpdateManager}.
	 */
	@Override
	protected void onStop() {
		super.onStop() ;
		UpdateNotifier.removeListener(this) ;
//		UpdateManager.getInstance().removeListener(this) ;
	}// onStop()

	/**
	 * Initializes the action bar of this view.
	 */
	private void initActionBar() {
		addActionBarItem(Type.Edit, LessonScreen.ITEM_EDIT) ;
	}// initActionBar()

	/**
	 * Handles the clicks on the action bar items.
	 */
	@Override
	public boolean onHandleActionBarItemClick(ActionBarItem item, int position) {
		switch (item.getItemId()) {
		case ITEM_EDIT :
			this.mark() ;
			break ;
			
		default :
			return super.onHandleActionBarItemClick(item, position);
		}// switch()

		return true ;
	}// onHandleActionBarItemClick(ActionBarItem, int)

	/**
	 * Displays a dialog with the choices for the new type of this lesson.
	 */
	private void mark() {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		String[] types = {"normal", "important", "examen"};
		int checkItem = this.lesson.getType() ;
		builder.setSingleChoiceItems(types, checkItem, new MarkListener(this));
		builder.setTitle("Marquer ce cours");
		builder.setIcon(RESULT_OK);
		Dialog dialog_return = builder.create();
		dialog_return.show() ;
	}// mark()
	
	/**
	 * OnClickListener for the marking of a lesson.
	 * 
	 * <p>Retrives the new lessen type and updates the database.
	 * 
	 * @author 	Schnell Michaël, Zanette Sébastien
	 */
	class MarkListener implements DialogInterface.OnClickListener {
		
		/**
		 * View containing the component attached to this listener.
		 */
		private LessonScreen container ;
		
		/**
		 * Sole constructor. 
		 * 
		 * @param 	container
		 * 			View containing the component attached to this listener
		 */
		public MarkListener(LessonScreen container) {
			super();
			this.container = container;
		}// MarkListener(LessonScreen)

		/**
		 * Handles the click on the attached component.
		 * 
		 * @param	actualView
		 * 			view of the component who has received a click event
		 */
		public void onClick(DialogInterface dialog, int item) {
			Lesson dispLesson = this.container.getLesson() ;
			// A new type has been selected
			if (item != dispLesson.getType()) {
				dispLesson.setType(item) ;
				Database db = new Database(this.container) ;
				db.updateLesson(dispLesson.getLessonId(), dispLesson.getSchedule(), dispLesson) ;
				this.container.init() ;
			}// if
			dialog.dismiss();
		}// onClick(View)
		
	}// class MarkListener

	/**
	 * Returns the instance of {@code Lesson} containing the information
	 * about the displayed lesson.
	 */
	private Lesson getIntentLesson() {
		return this.getIntent().getParcelableExtra("aaa.screen.lesson") ;               
	}// getIntentLesson()
	
	/**
	 * Returns the current instance of {@code Lesson} containing the 
	 * information about the displayed lesson.
	 * 
	 * @return	instance of {@code Lesson} containing the 
	 * 			information about the displayed lesson
	 */
	public Lesson getLesson() {
		return this.lesson ;
	}// getLesson()

	/**
	 * Initializes the view with the values from the current lesson.
	 */
	public void init() {
		this.items = new ArrayList<Item>();

		this.items.add(new SeparatorItem("Nom"));
		this.items.add(new DescriptionItem(this.lesson.getTitle()));

		this.items.add(new SeparatorItem("Date et Heure"));
		String formattedDate = new SimpleDateFormat("EEEE dd MMMM", Locale.FRANCE).format(this.lesson.getDate()) ;
		String hours = this.lesson.getTime().substring(this.lesson.getTime().indexOf(' ')+1) ;
		this.items.add(new DescriptionItem(StringUtils.capitalize(formattedDate)+" : "+hours));

		this.items.add(new SeparatorItem("Lieu"));
		this.items.add(new DescriptionItem(this.lesson.getRoom()));

		this.items.add(new SeparatorItem("Groupe"));
		String[] groups = LessonScreen.parseGroups(this.lesson.getGroups());
		for (String group : groups) {
			this.items.add(new DescriptionItem(group)) ;
		}// for

		this.items.add(new SeparatorItem("Enseigant"));
		String[] teachers = LessonScreen.parseTeachers(this.lesson.getTeacher());
		for (String teacher : teachers) {
			this.items.add(new DescriptionItem(teacher)) ;
		}// for

		this.items.add(new SeparatorItem("Statut"));
		this.items.add(new DescriptionItem(LessonScreen.typeToString(this.lesson.getType())));

		this.items.add(new SeparatorItem("Création du cours"));
		this.items.add(new DescriptionItem(StringUtils.capitalize(this.lesson.getCreated())));

		final ItemAdapter adapter = new ItemAdapter(this, this.items);
		this.setListAdapter(adapter) ;
	}// init()

	/**
	 * Parses a formatted {@code String} of groups and returns an array containing all 
	 * the groups.
	 * 
	 * @param 	groups
	 * 			formatted {@code String} of groups
	 * 
	 * @return	Array containing all the groups
	 */
	public static String[] parseGroups(String groups) {
		return groups.split(", ") ;
	}// parseGroup(String)

	/**
	 * Parses a formatted {@code String} of teachers and returns an array containing all 
	 * the teachers.
	 * 
	 * @param 	groups
	 * 			formatted {@code String} of teachers
	 * 
	 * @return	Array containing all the teachers
	 */
	public static String[] parseTeachers(String teachers) {
		return teachers.split(", ");
	}// parseTeachers(String)

	/**
	 * Returns a textual representation of the lesson type.
	 * 
	 * <p>The supported values are 0 (normal), 1 (important) and 2 (examen).
	 * 
	 * @param 	statut
	 * 			code for the lesson type
	 * 
	 * @return	name of the lessen type
	 */
	public static String typeToString (int type) {
		String[] items = {"normal", "important", "examen"};
		if (type < 0 || type >= items.length) {
			return items[0] ;
		}// if
		return items[type] ;
	}// typeToString(int)

	/**
	 * Used to display a dialog when the containing schedule is being updated.
	 */
	public void onUpdate(Object... args) {
		try {
			String scheduleName = (String)  args[0] ;
			int scheduleState   = (Integer) args[1] ;
			if (scheduleName.equals(this.lesson.getSchedule())) {
				if (scheduleState == STATUS_UPDATING) {
					if (this.updateDialog == null) {
						this.updateDialog = ProgressDialog.show(this, 
								"Chargement", "Mise à jour en cours ...", 
								true, true, new UpdateCancelListener(this)) ;
					}// if
				} else {
					if (this.updateDialog != null) {
						this.updateDialog.dismiss() ;
						this.updateDialog = null ;
					}// if
				}// if
			}// if
		} catch (Exception e) {/** Nothing to be done. */}//try
	}// onUpdate(Object...)

	/**
	 * OnCancelListener for the cancel action when the user wants to leave this 
	 * view while the schedule is being updated.
	 * 
	 * @author	Schnell Michaël, Zanette Sébastien
	 */
	class UpdateCancelListener extends Object implements OnCancelListener {
		
		/**
		 * View containing the component attached to this listener.
		 */
		protected LessonScreen container ;

		/**
		 * Sole constructor. 
		 * 
		 * @param 	container
		 * 			View containing the component attached to this listener
		 */
		public UpdateCancelListener(LessonScreen container) {
			super();
			this.container = container;
		}// UpdateCancelListener(LessonScreen)
		
		/**
		 * Handles the cancel action.
		 * 
		 * @param	actualView
		 * 			view of the component who has received a click event
		 */
		public void onCancel(DialogInterface dialog) {
			dialog.dismiss() ;
			this.container.onBackPressed() ;
		}// onCancel(DialogInterface)
		
	}// class UpdateCancelListener

}// class LessenScreen